﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System;
using System.Drawing;
using System.Drawing.Printing;
using System.Collections.Generic;
using System.Collections;


namespace PrinterPrinting
{
    public class PrinterController
    {
        public void PrintReciept(string printerName) 
        {            
            PrintDocument pd = new PrintDocument();
            pd.PrinterSettings.PrinterName = printerName;

            pd.PrintPage += pd_PrintPage;
            try
            {
                pd.Print();
            }
            catch (Exception e)
            {
                throw e;
            }
            
        }

        public List<string> getPrinterNames()
        {
            try
            {
                List<string> printerNames = new List<string>();
                foreach (string s in PrinterSettings.InstalledPrinters)
                {
                    printerNames.Add(s);
                    Console.WriteLine(s);
                }
                return printerNames;
            }
            catch(Exception e)
            {
                throw new Exception("Windows print service may be not started\n" + e.Message);
            }
        }

        private void pd_PrintPage(object sender, PrintPageEventArgs e)
        {
            Graphics g;
            int nameWidth = 30;
            int nameBreakAt = 20;
            int quantityWidth = 10;
            int unitPriceWidth = 12;
            int lineTotalWidth = 20;
            char sep = '_';
            decimal GrandTotal = 0;

            //

            g = e.Graphics;
            Font f = new Font("Courier New", 12);
            float fontHeight = f.GetHeight();

            int startX = 40;
            int startY = 60;
            int offset = 40;

            g.DrawString("This is a normal reciept",
                new Font("Courier New", 20),
                new SolidBrush(Color.Black),
                startX, startY);

            //

            List<Item> items = new List<Item>
            {
                new Item("Coffee", 2, 5000),
                new Item("Cookie in the center of Ho Chi Minh City", 10, 9000),
                new Item("Kit Kat", 10, 20000),
                new Item("Snack", 7, 90000),
                new Item("Ice Cream", 1, 10000),
                new Item("Something else", 2, 15000),
                new Item("Bánh trán trộn", 2, 15000)
            };

            string title = "NAME".PadRight(nameWidth)
                + "QUANTITY".PadLeft(quantityWidth)
                + "UNIT PRICE".PadLeft(unitPriceWidth)
                + "LINE TOTAL".PadLeft(lineTotalWidth);

            List<string> outputPrint = new List<string>();
            outputPrint.Add(title);

            //

            foreach (Item item in items)
            {
                GrandTotal += item.LineTotal;

                string quantity =
                    string.Format("{0}",
                    item.Quantiry).PadLeft(quantityWidth, sep);
                string unitPrice =
                    string.Format("{0:c}",
                    item.UnitPrice).PadLeft(unitPriceWidth, sep);
                string lineTotal =
                    string.Format("{0:c}",
                    item.LineTotal).PadLeft(lineTotalWidth, sep);

                string name, nameBreak;
                if (item.Name.Length > nameBreakAt)
                {
                    int breakIndex = nameBreakAt;
                    while (item.Name[breakIndex] != ' ')
                    {
                        breakIndex += 1;
                    }

                    nameBreak = item.Name
                              .Substring(breakIndex)
                              .Trim()
                              .PadRight(nameWidth, sep);

                    name = item.Name
                        .Substring(0, breakIndex)
                        .Trim()
                        .PadRight(nameWidth);

                    outputPrint.Add(name);
                    outputPrint.Add(
                        nameBreak
                        + quantity
                        + unitPrice
                        + lineTotal);

                }
                else
                {
                    name = item.Name.PadRight(nameWidth, sep);
                    outputPrint.Add(
                        name
                        + quantity
                        + unitPrice
                        + lineTotal);
                }
            }

            //

            foreach (string item in outputPrint)
            {
                Console.WriteLine(item);
                Console.WriteLine();

                g.DrawString(item,
                f,
                new SolidBrush(Color.Black),
                startX, startY + offset);

                offset += (int)fontHeight + 10;
            }
            offset += 30;
            g.DrawString("Grand Total :".PadRight(30)
                + string.Format("{0:c}", GrandTotal),
                f,
                new SolidBrush(Color.Black),
                startX, startY + offset);

            // 
        }


    }


    class Item
    {
        public Item()
        {
        }

        public Item(string name, decimal quantity, decimal unitPrice)
        {
            this.Name = name;
            this.Quantiry = quantity;
            this.UnitPrice = unitPrice;
        }

        private decimal price;

        public string Name
        {
            get;
            set;
        }

        public decimal UnitPrice
        {
            get;
            set;
        }

        public decimal Quantiry
        {
            get;
            set;
        }

        public string UnitPriceString
        {
            get
            {
                return string.Format("${0}", UnitPrice);
            }
        }

        public decimal LineTotal
        {
            get
            {
                return UnitPrice * Quantiry;
            }
        }

        public string LineTotalString
        {
            get
            {
                return string.Format("${0}", UnitPrice * Quantiry);
            }
        }
    }

}
